package com.log4jviewer.ui.preferences.filters;

import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotButton;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTable;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;

import utils.swtbot.UITest;

/**
 * The class that incapsulates all necessary functionality for simple "Filters" Page UI tests creating.
 * 
 * @author <a href="mailto:Daniil.Yaroslavtsev@gmail.com">Daniil Yaroslavtsev</a>
 */
public abstract class AbstractFiltersPageTest extends UITest {

    /** The UI testing bot. */
    private static SWTWorkbenchBot bot = getBot();

    /** The "Restore defaults" button. */
    private static SWTBotButton restoreDefaultsButton;

    /** The "Apply" button. */
    private static SWTBotButton applyButton;

    /** The "Cancel" button. */
    private static SWTBotButton cancelButton;

    /** The "OK" button. */
    private static SWTBotButton buttonOK;

    /** The "Add" filter button. */
    private static SWTBotButton addFilterButton;

    /** The "Add" filter rule button. */
    private static SWTBotButton addFilterRuleButton;

    /** The "Remove" filter button. */
    private static SWTBotButton removeFilterButton;

    /** The "Remove" filter rule button. */
    private static SWTBotButton removeFilterRuleButton;

    /** The filter table. */
    private static SWTBotTable filterTable;

    /** The filter rules table. */
    private static SWTBotTable filterRuleTable;

    private static FilterContentProvider filterContentProvider;

    private static FilterSettings filterSettings;

    private static FilterRuleSettings filterRuleSettings;

    @BeforeClass
    public static void beforeClass() {
        setupSWTBotParams();
        // BOT.resetWorkbench();  // set the workbench to it`s initial state

        closeUnnecessaryViewsIfNeeded();
        openFiltersPreferencesPage(); // Open the "Filters" page   
        findAndParsePageControls(); // and parse it`s controls. 
    }

    @Before
    public void beforeTest() {
        setInitialPageState();
    }

    @After
    public void afterTest() {
        setInitialPageState();
    }

    @AfterClass
    public static void afterClass() {
        closePreferencesDialog();
        doSleepBetweenTests();
    }

    /**
     * Opens the "Filters" preferences page.
     */
    protected static void openFiltersPreferencesPage() {
        bot.menu("Window").menu("Preferences").click();

        SWTBotTree tree = bot.tree();

        // Log4j-Viewer menu item
        SWTBotTreeItem item = tree.getTreeItem("Log4j-Viewer");
        item.doubleClick();

        SWTBotTreeItem filtersItem = item.getNode("Filters");
        filtersItem.doubleClick();
    }

    /**
     * Finds and parses the page controls.
     */
    protected static void findAndParsePageControls() {
        filterTable = bot.tableInGroup("Available filters");
        filterRuleTable = bot.tableInGroup("Filter's rules");

        addFilterButton = bot.buttonInGroup("Add", "Available filters");
        removeFilterButton = bot.buttonInGroup("Remove", "Available filters");

        addFilterRuleButton = bot.buttonInGroup("Add", "Filter's rules");
        removeFilterRuleButton = bot.buttonInGroup("Remove", "Filter's rules");

        restoreDefaultsButton = bot.button("Restore Defaults");
        applyButton = bot.button("Apply");
        cancelButton = bot.button("Cancel");
        buttonOK = bot.button("OK");

        filterContentProvider = FilterPreferencePage.getFilterContentProvider();
        filterSettings = FilterPreferencePage.getFilterSettings();
        filterRuleSettings = FilterPreferencePage.getFilterRulesSettings();

    }

    /**
     * Closes a preferences dialog without saving changes.
     * */
    protected static void closePreferencesDialog() {
        pressCancel();
    }

    // Getters
    /**
     * Gets the adds the filter button.
     * 
     * @return the adds the filter button
     */
    protected static SWTBotButton getAddFilterButton() {
        return addFilterButton;
    }

    /**
     * Gets the adds the filter rule button.
     * 
     * @return the adds the filter rule button
     */
    protected static SWTBotButton getAddFilterRuleButton() {
        return addFilterRuleButton;
    }

    /**
     * Gets the removes the filter button.
     * 
     * @return the removes the filter button
     */
    protected static SWTBotButton getRemoveFilterButton() {
        return removeFilterButton;
    }

    /**
     * Gets the removes the filter rule button.
     * 
     * @return the removes the filter rule button
     */
    protected static SWTBotButton getRemoveFilterRuleButton() {
        return removeFilterRuleButton;
    }

    /**
     * Gets the filter table.
     * 
     * @return the filter table
     */
    protected static SWTBotTable getFilterTable() {
        return filterTable;
    }

    /**
     * Gets the filter rule table.
     * 
     * @return the filter rule table
     */
    protected static SWTBotTable getFilterRuleTable() {
        return filterRuleTable;
    }

    protected static FilterContentProvider getFilterContentProvider() {
        return filterContentProvider;
    }

    protected static FilterSettings getFilterSettings() {
        return filterSettings;
    }

    protected static FilterRuleSettings getFilterRuleSettings() {
        return filterRuleSettings;
    }

    /**
     * Adds one filter.
     */
    protected static void addFilter() {
        addFilterButton.click();
    }

    /**
     * Adds the filters.
     * 
     * @param filterCount
     *            - filters to add count.
     */
    protected static void addFilters(final int filterCount) {
        filterTable.setFocus();
        for (int i = 0; i < filterCount; i++) {
            addFilter();
        }
    }

    /**
     * Removes the specified filter.
     * 
     * @param filterIndex
     *            - table row index for the specified filter.
     */
    protected static void removeFilter(final int filterIndex) {
        filterTable.select(filterIndex);
        removeFilterButton.click();
    }

    /**
     * Removes all filters.
     */
    protected static void removeAllFilters() {
        int riltersCount = filterTable.rowCount();
        for (int i = 0; i < riltersCount; i++) {
            removeFilter(0);
        }
    }

    /**
     * Adds one filter rule.
     */
    protected static void addFilterRule() {
        addFilterRuleButton.click();
    }

    /**
     * Adds the filter rules.
     * 
     * @param filterIndex
     *            the filter index
     * @param rulesToAddCount
     *            the rules to add count
     */
    protected static void addFilterRules(final int filterIndex, final int rulesToAddCount) {
        filterTable.select(filterIndex); // highlight the selected filter in Table
        for (int i = 0; i < rulesToAddCount; i++) {
            addFilterRuleButton.click(); // add n filter rules
        }
    }

    /**
     * Removes the specified filter rule from specified filter.
     * 
     * @param filterIndex
     *            - the filter index.
     * @param filterRuleIndex
     *            - the filter rule index.
     */
    protected static void removeFilterRule(final int filterIndex, final int filterRuleIndex) {
        filterTable.select(filterIndex); // highlight the selected filter in Table
        filterRuleTable.select(filterRuleIndex);
        removeFilterRuleButton.click(); // remove selected filter rule
    }

    /**
     * Removes all filter rules from filter, specified by index.
     * 
     * @param filterIndex
     *            - the filter index.
     */
    protected static void removeAllFilterRules(final int filterIndex) {
        int filterRulesCount = filterRuleTable.rowCount();
        for (int i = 0; i < filterRulesCount; i++) {
            removeFilterRule(filterIndex, 0);
        }
    }

    // "press ... button" methods

    /**
     * Presses an "Apply" button.
     * */
    protected static void pressApply() {
        applyButton.click(); // apply changes
    }

    /**
     * Presses the OK button.
     */
    protected static void pressOk() {
        buttonOK.click(); // apply changes
    }

    /**
     * Presses the Cancel button.
     */
    protected static void pressCancel() {
        cancelButton.click(); // apply changes
    }

    /**
     * Presses the "Restore Defaults" button.
     */
    protected void pressRestoreDefaultsButton() {
        restoreDefaultsButton.click();
    }

    /**
     * Clears all tables by removing all filters.
     * */
    protected static void setInitialPageState() {
        removeAllFilters();
        pressApply();
    }

}
